#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
#include <SoftwareSerial.h>
// ***温湿度传感器*** ------------------------------------------------------
#define DHTPIN  8
#define DHTTYPE DHT11 // 定义类型，DHT11或者其它
DHT dht(DHTPIN, DHTTYPE); // 进行初始设置 
float humidity = 0.0; // 空气湿度
float temperature = 0.0; // 气温
// ***土壤湿度传感器*** ----------------------------------------------------
#define MOISTURE A0 // 定义 AO 引脚
int Moisture = 0; // 土壤湿度
// ***光敏传感器*** -------------------------------------------------------
#define LIGHT   A1 // 定义 A1 引脚
int light = 0;
// ***二氧化碳传感器*** ---------------------------------------------------
#define RX_PIN 0
#define TX_PIN 1
SoftwareSerial co2Sensor(RX_PIN, TX_PIN); // 设置软件串口
const int packetSize = 6; // 传感器的数据包大小
byte packet[packetSize];
int co2 = 0; // CO2浓度
// ***OLED屏幕*** -------------------------------------------------------
#define OLED_RESET     4
Adafruit_SSD1306 display(128, 64, &Wire,OLED_RESET);
// ***函数定义*** -------------------------------------------------------
void GetDHTData(); // 获取温湿度传感器数据并打印
void GetMoisData(); // 获取土壤传感器适度值并打印
void GetLightData(); // 获取光敏传感器数据并打印
void GetCO2Data(); // 获取二氧化碳浓度数据并打印
void WordPrint(); // 在OLED屏幕上打印数据
// ***SETUP*** ---------------------------------------------------------
void setup() {
  Serial.begin(9600);
  dht.begin(); //DHT开始工作
  pinMode(MOISTURE, INPUT);//定义A0为输入模式
  pinMode(LIGHT, INPUT);//定义A1为输入模式
  co2Sensor.begin(9600); // 开启CO2传感器
  display.begin(SSD1306_SWITCHCAPVCC,0x3C); // OLED初始化

  delay(1000); // delay 1s 等待传感器开启
}
// ***LOOP*** --------------------------------------------------------
void loop() {
  GetDHTData();
  GetMoisData();
  GetLightData();
  GetCO2Data();
  WordPrint();
  display.display();
  delay(2000);
}
// ***函数实现*** ----------------------------------------------------
void GetDHTData(){
  // 两次检测之间，要等几秒钟，这个传感器有点慢。
  // 读温度或湿度要用250毫秒
  humidity = dht.readHumidity();//读湿度
  temperature = dht.readTemperature();//读温度，默认为摄氏度
  Serial.print("Humidity: ");//湿度
  Serial.println(humidity);
  Serial.print("Temperature: ");//温度
  Serial.print(temperature);
  Serial.println(" ℃ ");
}

void GetMoisData(){
  //串口返回测量数据
  Moisture = analogRead(Moisture); // 读取AO的数值
  Serial.print("Moisture: ");
  Serial.println(Moisture);
  // 经过测试：< 500太湿，目标范围是500-750，> 750足够干，可以浇水
}

void GetLightData(){
  light = analogRead(LIGHT);  // 读取A1的数值
  Serial.print("Light:");
  Serial.println(light);
}

void GetCO2Data(){
  // 读取数据
  if (co2Sensor.available() >= packetSize) {
    for (int i = 0; i < packetSize; i++) {
      // 读取传感器数据
      packet[i] = co2Sensor.read();
    }

    // 直接计算CO2浓度，不进行校验和检验
    co2 = (packet[1] * 256) + packet[2];
    Serial.print("CO2 Concentration: ");
    Serial.print(co2);
    Serial.println(" PPM");
  }
}

void WordPrint(){
  // 清除屏幕
  display.clearDisplay();
 
  // 设置字体颜色,白色可见
  display.setTextColor(SSD1306_WHITE);
 
  //设置字体大小
  display.setTextSize(1.5);
 
  //设置光标位置
  display.setCursor(0, 0);
  display.print("Humidity: "); // 空气湿度
  display.println(humidity);
  display.setCursor(0, 10);
  display.print("Temperature: "); // 温度
  display.print(temperature);
  display.println(" C");
  display.setCursor(0, 20);
  display.print("Moisture: "); // 土壤湿度
  display.println(Moisture);
  display.setCursor(0, 30);
  if (Moisture < 500) display.println("Too moist!");
  else if(Moisture >= 500 && Moisture <= 750) display.println("Good!");
  else display.println("Too dry!");
  display.setCursor(0, 40);
  display.print("Light: "); // 光照情况
  display.println(light);
  display.setCursor(0, 50);
  display.println("CO2 Concentration: "); // CO2浓度
  display.print(co2);
  display.println(" PPM");
}